package intf;

import basic.QrCodeBasic;
import com.alibaba.fastjson.JSONObject;
import common.WxApi;
import common.WxBaseMsg;
import common.WxPattern;
import okhttp3.*;
import okhttp3.FormBody.Builder;
import org.apache.commons.io.IOUtils;
import org.jetbrains.annotations.NotNull;
import result.QrcodeBuffer;
import result.WxAccessToken;
import utils.JsonUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * 微信请求
 *
 * @author gzkemays
 * @since 2021/12/13 18:03
 */
public class WxRequest {
  /**
   * 获取 accessToken
   *
   * @param baseMsg 基本信息
   * @return 返回的 token 以及时效性
   */
  public static WxAccessToken getAccessToken(WxBaseMsg baseMsg) {
    try {
      ResponseBody body = doGet(WxApi.accessTokenApi(baseMsg));
      String string = body.string();
      if (JsonUtils.isJson(string)) {
        JSONObject json = JSONObject.parseObject(string);
        if (json.get(WxPattern.ACCESS_TOKEN) != null) {
          WxAccessToken wxAccessToken = new WxAccessToken();
          wxAccessToken.setAccessToken(json.getString(WxPattern.ACCESS_TOKEN));
          wxAccessToken.setExpires(json.getLong(WxPattern.EXPIRE));
          return wxAccessToken;
        }
        return JSONObject.parseObject(string, WxAccessToken.class);
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
    return null;
  }

  public static QrcodeBuffer getQrcode(QrCodeBasic basic) {
    try {
      ResponseBody body = doPost(WxApi.qrcode(basic), basic.transitionMap(), true);
      byte[] is = copyStream(body.byteStream()).toByteArray();
      ByteArrayInputStream bis = new ByteArrayInputStream(is);
      String byteStr = IOUtils.toString(new ByteArrayInputStream(is), StandardCharsets.UTF_8);
      if (JsonUtils.isJson(byteStr)) {
        return JSONObject.parseObject(byteStr, QrcodeBuffer.class);
      }
      if (basic.getGeneratePath() != null) {
        OutputStream os = new FileOutputStream(basic.getGeneratePath());
        int len;
        byte[] bytes = new byte[1024];
        while ((len = bis.read(bytes)) != -1) {
          os.write(bytes, 0, len);
          os.flush();
        }
        os.close();
        return new QrcodeBuffer(true);
      }
      return new QrcodeBuffer(bis);
    } catch (IOException e) {
      e.printStackTrace();
    }
    throw new NullPointerException("流为空");
  }

  public static ResponseBody doGet(String url) {
    return getResponseBody(new OkHttpClient().newCall(new Request.Builder().url(url).build()));
  }

  public static ResponseBody doPost(String url, Map<String, String> map, boolean json) {
    Call call;
    Builder builder = new Builder();
    for (Map.Entry<String, String> entry : map.entrySet()) {
      builder.add(entry.getKey(), entry.getValue());
    }
    FormBody formBody = builder.build();
    if (json) {
      String jsonStr = JSONObject.toJSONString(map);
      MediaType mediaType = MediaType.parse("application/json;charset=UTF-8");
      RequestBody requestBody =
          FormBody.create(mediaType, jsonStr.getBytes(StandardCharsets.UTF_8));
      call = new OkHttpClient().newCall(new Request.Builder().url(url).post(requestBody).build());
    } else {
      call = new OkHttpClient().newCall(new Request.Builder().url(url).post(formBody).build());
    }
    return getResponseBody(call);
  }

  public static ByteArrayOutputStream copyStream(InputStream stream) {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    try {
      byte[] buffer = new byte[1024];
      int len;
      while ((len = stream.read(buffer)) > -1) {
        baos.write(buffer, 0, len);
      }
      baos.flush();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return baos;
  }

  @NotNull
  private static ResponseBody getResponseBody(Call call) {
    try {
      Response execute = call.execute();
      ResponseBody body = execute.body();
      if (body != null) {
        return body;
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
    throw new NullPointerException("body 为空");
  }
}
